import java.util.*;
import java.util.stream.Collectors;

import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.*;

/**
 * @Author: Liu, Yunfeng
 * @DateTime: 2020/5/19 21:50
 * @Description: 用流收集数据
 */
public class CollectWithStream {


    public static void main(String[] args) {

        List<Dish> dishList = Arrays.asList(new Dish("beef", false, 700, Type.MEAT),
                new Dish("pork", false, 800, Type.MEAT),
                new Dish("chicken", false, 400, Type.MEAT),
                new Dish("french frice", true, 530, Type.OTHER),
                new Dish("rice", true, 350, Type.OTHER),
                new Dish("season fruit", true, 120, Type.OTHER),
                new Dish("pizza", true, 550, Type.OTHER),
                new Dish("prawns", false, 300, Type.FISH),
                new Dish("salmon", false, 450, Type.FISH)
        );
        //元素归约
        long dishCount = dishList.stream().collect(Collectors.counting());
        System.out.println(dishCount);
        long dishCount2 = dishList.stream().count();
        System.out.println(dishCount2);
        System.out.println("*****************************************");

        //查询最大最小值
        /*Comparator<Dish> dishCaloriesComparator = dishList.stream().collect(comparingInt(Dish::getCalories));
        Optional<Dish> mostCaloriesDish = dishList.stream().collect(maxBy(dishCaloriesComparator));*/


        //汇总,统计数据
        IntSummaryStatistics summaryStatistics = dishList.stream().collect(summarizingInt(Dish::getCalories));
        System.out.println(summaryStatistics.getSum());
        System.out.println(summaryStatistics.getMax());
        System.out.println(summaryStatistics.getAverage());
        System.out.println(summaryStatistics.getCount());
        System.out.println("*****************************************");


        int totalCalories = dishList.stream().collect(summingInt(Dish::getCalories));
        System.out.println(totalCalories);
        System.out.println("*****************************************");

        //连接字符串，join
        String menu = dishList.stream().map(Dish::getName).collect(joining());
        System.out.println(menu);
        String menu1 = dishList.stream().map(Dish::getName).collect(joining(", "));
        System.out.println(menu1);
        System.out.println("*****************************************");

        //广义归约 reducing
        int totalCaloties = dishList.stream().collect(reducing(0, Dish::getCalories, Integer::sum));
        System.out.println(totalCalories);
        Optional<Dish> mostCalotiesDish = dishList.stream().collect(reducing((dish1, dish2) -> dish1.getCalories() > dish2.getCalories() ? dish1 : dish2));
        System.out.println(mostCalotiesDish.get().getName());
        System.out.println("*****************************************");

        //分组 group by
        Map<Type, List<Dish>> groupByType = dishList.stream().collect(groupingBy(Dish::getType));
        System.out.println(groupByType);
        Map<Type, Long> groupAndCount = dishList.stream().collect(groupingBy(Dish::getType, counting()));
        System.out.println(groupAndCount);
        Map<Type, Dish> groupAndmax = dishList.stream().collect(groupingBy(Dish::getType,
                collectingAndThen(maxBy(Comparator.comparingInt(Dish::getCalories)),Optional::get)));
        System.out.println(groupAndmax);
        Map<Type,Integer> groupAndTotalCalories = dishList.stream().collect(groupingBy(Dish::getType,summingInt(Dish::getCalories)));
        System.out.println(groupAndTotalCalories);
        Map<Type,Set<CaloriesLevel>> caloriesLevelByType = dishList.stream().collect(groupingBy(Dish::getType,mapping(dish ->
        {
            if(dish.getCalories()>=700)
                return CaloriesLevel.FAT;
            else if(dish.getCalories()<400)
                return CaloriesLevel.NORMAL;
            else
                return CaloriesLevel.LOW;
        },toSet())));
        System.out.println(caloriesLevelByType);
        System.out.println("*****************************************");

        //分区 partition by
        Map<Boolean,List<Dish>> partitionedmenu = dishList.stream().collect(partitioningBy(Dish::isVagetarian));
        System.out.println(partitionedmenu);


    }

}
